package com.tree.thread.pubsub;

import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName com.tree.thread.pubsub
 * Description: <类功能描述>. <br>
 * <p>
 * 使用lock\condition解决生产者消费者问题
 * </p>
 * @Author tree
 * @Date 2019-11-02 09:23
 * @Version 1.0
 */
public class LockTest {



    public static void main(String[] args) {
        LockStorage storage = new LockStorage();
        for(int i = 0; i< 3; i++){
            new Thread(new Producer(storage),"生产者-"+i).start();
            new Thread(new Consumer(storage),"消费者-"+i).start();
        }
    }

    static class LockStorage implements IStorage{
        private int count = 0;

        private final static int FULL = 10;

        private Lock lock;

        private Condition emptyCondition;

        private Condition fullCondition;
        {
            lock = new ReentrantLock();
            emptyCondition = lock.newCondition();
            fullCondition = lock.newCondition();
        }

        @Override
        public void produce(){
            lock.lock();
            try{
                    String threadName = Thread.currentThread().getName();
                    System.out.println("生产者【" + threadName+ "】进入生产，count="+count);
                    while (count >= FULL){
                        try {
                            System.out.println("生产者【" +threadName+ "】仓库已满， 等待。。。。。。。count="+count);
                            fullCondition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    count++;
                    if(count > FULL){
                        System.err.println("生产者【" + threadName+ "】并发有问题， 超出最大容量， count="+count);
                    }
                    System.out.println("生产者【" + threadName+ "】生产一个产品，现库存" + count);
                    emptyCondition.signalAll();
            }finally {
                lock.unlock();
            }
        }

        @Override
        public void consume(){
            lock.lock();
            try{
                    String threadName = Thread.currentThread().getName();
                    System.out.println("消费者【" + threadName+ "】消费，count="+count);
                    while (count <= 0){
                        try {

                            System.out.println("消费者【" + threadName+ "】仓库为空， 等待。。。。。。。count="+count);
                            emptyCondition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    count--;
                    if(count < 0){
                        System.err.println("消费者【" + threadName+ "】消费者并发有问题， 出现超卖现象， count="+count);
                    }
                    System.out.println("消费者【" + Thread.currentThread().getName()
                            + "】消费一个产品，现库存" + count);
                    fullCondition.signalAll();
            }finally {
                lock.unlock();
            }
        }
    }

//    static class Producer implements Runnable{
//
//        private Storage storage;
//        private Random random = new Random();
//
//        public Producer(Storage storage){
//            this.storage = storage;
//        }
//
//        @Override
//        public void run() {
//            while (true) {
//                try {
//                    Thread.sleep(random.nextInt(1000));
//                    storage.produce();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//    }
//
//    static class Consumer implements Runnable{
//
//        private Storage storage;
//        private Random random = new Random();
//
//        public Consumer(Storage storage){
//            this.storage = storage;
//        }
//
//        @Override
//        public void run() {
//            while (true) {
//                try {
//                    Thread.sleep(random.nextInt(1000));
//                    storage.consume();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//    }
}

